package com.wei.web.middleware.httpfilter.registrar.filter.factory;

import com.wei.web.middleware.httpfilter.filter.init.FilterInitialize;
import com.wei.web.middleware.httpfilter.registrar.handler.ExpressionHandler;
import com.wei.web.middleware.httpfilter.registrar.model.FilterConfigDTO;
import jakarta.servlet.Filter;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;

import java.util.HashSet;
import java.util.List;

public abstract class AbstractFilterRegistrarFactoryBean implements FactoryBean<FilterRegistrationBean>, ApplicationContextAware, InitializingBean {

    protected FilterConfigDTO filterConfig;

    protected String filterName;

    protected Integer filterOrder;

    protected List<String> urlPatterns;

    protected ApplicationContext applicationContext;

    protected ExpressionHandler expressionHandler;

    public AbstractFilterRegistrarFactoryBean() {
    }

    public abstract Filter getFilter();

    @Override
    public void afterPropertiesSet() throws Exception {
        expressionHandler = new ExpressionHandler(this.applicationContext);
    }

    @Override
    public boolean isSingleton() {
        return true;
    }

    @Override
    public Class<?> getObjectType() {
        return FilterRegistrationBean.class;
    }

    @Override
    public FilterRegistrationBean getObject() throws Exception {
        Filter filter = getFilter();
        if (FilterInitialize.class.isAssignableFrom(filter.getClass())){
            ((FilterInitialize) filter).init(filterConfig);
        }

        List<String> newUrlPatterns = expressionHandler.evaluateValue(urlPatterns);
        FilterRegistrationBean<Filter> filterRegistrationBean = new FilterRegistrationBean<>();
        filterRegistrationBean.setUrlPatterns(newUrlPatterns);
        filterRegistrationBean.setFilter(filter);
        filterRegistrationBean.setOrder(filterOrder);
        filterRegistrationBean.setName(filterName);
        return filterRegistrationBean;
    }

    @Override
    public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
        this.applicationContext = applicationContext;
    }

    public String getFilterName() {
        return filterName;
    }

    public void setFilterName(String filterName) {
        this.filterName = filterName;
    }

    public Integer getFilterOrder() {
        return filterOrder;
    }

    public void setFilterOrder(Integer filterOrder) {
        this.filterOrder = filterOrder;
    }

    public List<String> getUrlPatterns() {
        return urlPatterns;
    }

    public void setUrlPatterns(List<String> urlPatterns) {
        this.urlPatterns = urlPatterns;
    }


    public ApplicationContext getApplicationContext() {
        return applicationContext;
    }

    public FilterConfigDTO getFilterConfig() {
        return filterConfig;
    }

    public void setFilterConfig(FilterConfigDTO filterConfig) {
        this.filterConfig = filterConfig;
    }
}

